﻿using System;
using System.Collections;

namespace ADTLists
{
    public class ADTGenericArray<T> : ADT
    {
        private T[] dataStorage;

        public ADTGenericArray()
        {
            size = 0;
            dataStorage = new T[0];
        }

        public override object GetElementFromStart()
        {
            if (dataStorage != null && size > 0)
            {
                return dataStorage[0];
            }
            else
            {
                throw new Exception("Error while getting the 1st element");
            }
        }

        public override object GetElementFromEnd()
        {
            if (dataStorage != null && size > 0)
            {
                return dataStorage[size - 1];
            }
            else
            {
                throw new Exception("Error while getting the last element");
            }
        }

        public override object GetElementFromPosition(int position)
        {
            if (dataStorage != null && size > position)
            {
                return dataStorage[position];
            }
            else
            {
                throw new Exception("Error while getting the element #" + position);
            }
        }

        public override void DelFromStart()
        {
            if (dataStorage != null && size > 0)
            {
                size--;
                T[] tempDataStorage = dataStorage;
                dataStorage = new T[size];
                tempDataStorage.CopyTo(dataStorage, 1);
                tempDataStorage = null;
            }
            else
            {
                throw new Exception("Error while deleting the 1st element");
            }
        }

        public override void DelFromEnd()
        {
            if (dataStorage != null && size > 0)
            {
                size--;
                T[] tempDataStorage = dataStorage;
                dataStorage = new T[size];
                Array.Copy(tempDataStorage, 0, dataStorage, 0, size);
                tempDataStorage = null;
            }
            else
            {
                throw new Exception("Error while deleting the last element");
            }
        }

        public override void DelFromPosition(int position)
        {
            if (dataStorage != null && position < size)
            {
                size--;
                T[] tempDataStorageBefore = new T[position];
                T[] tempDataStorageAfter = new T[size - position - 1];
                Array.Copy(dataStorage, 0, tempDataStorageBefore, 0, position);
                Array.Copy(dataStorage, position + 1, tempDataStorageAfter, 0, size - position - 2);
                dataStorage = new T[size];
                Array.Copy(tempDataStorageBefore, 0, dataStorage, 0, tempDataStorageBefore.Length);
                Array.Copy(tempDataStorageAfter, 0, dataStorage, position + 1, tempDataStorageAfter.Length);
                tempDataStorageBefore = null;
                tempDataStorageAfter = null;
            }
            else
            {
                throw new Exception("Error while deleting the element #" + position);
            }
        }

        public override void AddToStart(object element)
        {
            if (dataStorage != null && size >= 0)
            {
                size++;
                T[] tempDataStorage = dataStorage;
                dataStorage = new T[size];
                dataStorage[0] = (T)element;
                tempDataStorage.CopyTo(dataStorage, 1);
                tempDataStorage = null;
            }
            else
            {
                throw new Exception("Error while adding the 1st element");
            }
        }

        public override void AddToEnd(object element)
        {
            if (dataStorage != null && size >= 0)
            {
                size++;
                T[] tempDataStorage = dataStorage;
                dataStorage = new T[size];
                dataStorage[size - 1] = (T)element;
                tempDataStorage.CopyTo(dataStorage, 0);
                tempDataStorage = null;
            }
            else
            {
                throw new Exception("Error while adding the last element");
            }
        }

        public override void AddToPosition(object element, int position)
        {
            if (dataStorage != null && size >= 0)
            {
                size++;
                T[] tempDataStorageBefore = new T[position];
                T[] tempDataStorageAfter = new T[size - position - 1];
                Array.Copy(dataStorage, 0, tempDataStorageBefore, 0, position);
                Array.Copy(dataStorage, position, tempDataStorageAfter, 0, size - position - 1);
                dataStorage = new T[size];
                Array.Copy(tempDataStorageBefore, 0, dataStorage, 0, tempDataStorageBefore.Length);
                Array.Copy(tempDataStorageAfter, 0, dataStorage, position + 1, tempDataStorageAfter.Length);
                dataStorage[position] = (T)element;
                tempDataStorageBefore = null;
                tempDataStorageAfter = null;
            }
            else
            {
                throw new Exception("Error while adding the element #" + position);
            }
        }

        public override void SetFirst(object element)
        {
            if (size > 0 && dataStorage != null)
            {
                dataStorage[0] = (T)element;
            }
            else
            {
                throw new Exception("Error while setting the 1st element");
            }
        }

        public override void SetLast(object element)
        {
            if (size > 0 && dataStorage != null)
            {
                dataStorage[size - 1] = (T)element;
            }
            else
            {
                throw new Exception("Error while setting the last element");
            }
        }

        public override void SetToPosition(object element, int position)
        {
            if (size > 0 && dataStorage != null && position < size)
            {
                dataStorage[position] = (T)element;
            }
            else
            {
                throw new Exception("Error while setting the element #" + position);
            }
        }

        public override void Clear()
        {
            size = 0;
            dataStorage = new T[0];
        }

        public override IEnumerator GetEnumerator()
        {
            throw new NotImplementedException();
        }
    }
}
